
package com.scs.application.modules.settlement.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.scs.application.core.model.CommonResult;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.BeanValidators;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.modules.base.request.HospitalMaterialRequest;
import com.scs.application.modules.base.service.HospitalMaterialService;
import com.scs.application.modules.base.service.HospitalThirdPlatformService;
import com.scs.application.modules.base.vo.HospitalMaterialVO;
import com.scs.application.modules.msg.service.PushedRecordService;
import com.scs.application.modules.settlement.dto.StockDTO;
import com.scs.application.modules.settlement.entity.Stock;
import com.scs.application.modules.settlement.mapper.StockMapper;
import com.scs.application.modules.settlement.request.StockQueryRequest;
import com.scs.application.modules.settlement.service.StockService;
import com.scs.application.modules.thirdparty.erp.request.StockRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 库存管理 service 实现
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class StockServiceImpl extends BaseServiceImpl<StockMapper, Stock> implements StockService {

    @Autowired
    private HospitalMaterialService hospitalMaterialService;

    @Autowired
    private HospitalThirdPlatformService hospitalThirdPlatformService;

    @Autowired
    private PushedRecordService pushedRecordService;

    @Override
    public List<Stock> list(StockQueryRequest request) {
        List<Stock> list = this.list(Wrappers.<Stock>query()
                .like(StringUtils.isNotBlank(request.getHospitalName()), "hospital_name", request.getHospitalName())
                .like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName())
                .like(StringUtils.isNotBlank(request.getWarehouseName()), "warehouse_name", request.getWarehouseName())
                .like(StringUtils.isNotBlank(request.getMaterialName()), "material_name", request.getMaterialName())
                .like(StringUtils.isNotBlank(request.getMaterialSpec()), "material_spec", request.getMaterialSpec())
                .like(StringUtils.isNotBlank(request.getManufacturerName()), "manufacturer_name", request.getManufacturerName())
                .between(request.getBeginPrice() != null && request.getEndPrice() != null, "price", request.getBeginPrice(), request.getEndPrice())
                .between(request.getBeginExpiredDate() != null && request.getEndExpiredDate() != null, "expired_date", request.getBeginExpiredDate(), request.getEndExpiredDate())
                .orderByDesc("gmt_modified")
        );
        return list;
    }

    @Override
    public IPage<Stock> page(StockQueryRequest request) {
        request.setHospitalId(UserUtils.getHospitalId());
        IPage page = this.page(request.getPage(), Wrappers.<Stock>query()
                .like(StringUtils.isNotBlank(request.getLot()), "lot", request.getLot())
                .eq(StringUtils.isNotBlank(request.getHospitalId()), "hospital_id", request.getHospitalId())
                .like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName())
                .like(StringUtils.isNotBlank(request.getWarehouseName()), "warehouse_name", request.getWarehouseName())
                .like(StringUtils.isNotBlank(request.getMaterialName()), "material_name", request.getMaterialName())
                .like(StringUtils.isNotBlank(request.getMaterialSpec()), "material_spec", request.getMaterialSpec())
                .like(StringUtils.isNotBlank(request.getManufacturerName()), "manufacturer_name", request.getManufacturerName())
                .between(request.getBeginPrice() != null && request.getEndPrice() != null, "price", request.getBeginPrice(), request.getEndPrice())
                .between(request.getBeginExpiredDate() != null && request.getEndExpiredDate() != null, "expired_date", request.getBeginExpiredDate(), request.getEndExpiredDate())
                .orderByAsc("material_name")
        );
        return page;
    }

    @Override
    public IPage<Stock> pageForSupplier(StockQueryRequest request) {
        if (UserUtils.isSupplier()) {
            request.setSupplierId(UserUtils.getSupplierId());
        }

        return this.baseMapper.pageForSupplier(request.getPage(), request);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRealtime(List<StockDTO> stockDTOs) {

        List<HospitalMaterialVO> hms = hospitalMaterialService.listVO(new HospitalMaterialRequest());
        // 以耗材编码作为key
        Map<String, HospitalMaterialVO> map = hms.parallelStream().filter(o -> StringUtils.isNotBlank(o.getMaterialCode()))
                .collect(Collectors.toMap(o -> o.getMaterialCode(), o -> o, (o1, o2) -> o1));

        List<Stock> stocks = Lists.newArrayList();
        Stock stock;

        // 清除之前医院下的库存
        this.remove(Wrappers.<Stock>query().eq("hospital_id", UserUtils.getHospitalId()));

        for (StockDTO stockDTO : stockDTOs) {
            stock = new Stock();
            BeanUtils.copyProperties(stockDTO, stock, Stock.class);

            HospitalMaterialVO vo = map.get(stockDTO.getMaterialCode());
            if (vo == null) {
                log.warn("耗材编码 {} 在MSCM系统中不存在，请注意", stockDTO.getMaterialCode());
                continue;
            }
            stock.setHospitalId(vo.getHospitalId())
                    .setHospitalName(UserUtils.getHospital().getName())
                    .setSupplierId(vo.getSupplierId())
                    .setSupplierName(vo.getSupplierName())
                    .setMaterialId(vo.getMaterialId())
                    .setMaterialSpecId(vo.getMaterialSpecId())
                    .setMaterialName(vo.getMaterialName())
                    .setMaterialSpec(vo.getMaterialSpec())
                    .setManufacturerId(vo.getManufacturerId())
                    .setManufacturerName(vo.getManufacturerName())
                    .setExpiredDate(stock.getExpiredDate())
                    .setHospitalMaterialId(vo.getId())// 添加耗材主键id
            ;
            stocks.add(stock);
        }

        if (!stocks.isEmpty()) {
            this.saveBatch(stocks);
            pushedRecordService.pushVxBusCommonAsync(
                    stocks.stream().map(Stock::getSupplierId).distinct().collect(Collectors.toList()),
                    stocks.get(0).getHospitalName(),
                    "实时库存推送成功",
                    "stock_now_index"
            );
        }

        // todo 上一次库存数据加入到历史库存中
        // List<Stock> list = this.list(Wrappers.<Stock>query().eq("hospital_id", UserUtils.getHospitalId()));

    }

    @Override
    public List<String> realtime(List<StockDTO> stockDTOS) {
        List<String> messageList = Lists.newArrayList();
        for (int i = 0; i < stockDTOS.size(); i++) {
            try {
                BeanValidators.validateWithException(validator, stockDTOS.get(i));
            } catch (ConstraintViolationException e) {
                String message = String.format("第%d行数据校验失败，错误原因：%s",
                        i + 1,
                        StringUtils.join(BeanValidators.extractMessage(e), ";"));
                log.warn(message);
                messageList.add(message);
            }
        }
        saveRealtime(stockDTOS);
        return messageList;
    }

    @Override
    public boolean saveCascadeById(Stock entity) {
        entity.setHospitalId(UserUtils.getHospitalId())
                .setHospitalName(UserUtils.getHospital().getName());
        return super.saveCascadeById(entity);
    }

    @Override
    public CommonResult getStockERP(StockRequest request) {
        HospitalMaterialRequest hospitalMaterialRequest = new HospitalMaterialRequest();
        hospitalMaterialRequest.setHospitalId(request.getHospitalId());
        hospitalMaterialRequest.setThirdMaterialId(request.getThirdMaterialId());
        List<HospitalMaterialVO> hmList = hospitalMaterialService.listVO(hospitalMaterialRequest);

        List<String> mIdList = hmList.stream().map(hm -> hm.getMaterialSpecId()).collect(Collectors.toList());
        if(mIdList.isEmpty()){
            return CommonResult.ok("没有可查询的库存信息");
        }
        List<Stock> stockList = this.list(Wrappers.<Stock>query().eq("hospital_id", request.getHospitalId()).in("material_spec_id", mIdList));
        return CommonResult.ok("操作成功",stockList);
    }
}
